package com.ruoyi.framework.websocket;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.HandshakeInterceptor;

import java.util.Map;

/**
 * 用户握手拦截器
 * 在WebSocket握手阶段提取并验证用户信息，绑定到会话属性中
 */
public class UserHandshakeInterceptor implements HandshakeInterceptor {

    /**
     * 握手前执行：提取用户信息并验证
     * @param request 服务器HTTP请求
     * @param response 服务器HTTP响应
     * @param wsHandler WebSocket处理器
     * @param attributes 用于存储会话属性的Map（将传递给WebSocketSession）
     * @return 是否允许握手继续（true：允许，false：拒绝）
     */
    @Override
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response,
                                   WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
        
        // 将ServerHttpRequest转换为ServletServerHttpRequest以获取HTTP请求细节
        if (request instanceof ServletServerHttpRequest servletRequest) {
            HttpServletRequest httpRequest = servletRequest.getServletRequest();
            
            // 1. 从请求参数中获取用户ID（适用于无状态场景）
            String userId = httpRequest.getParameter("userId");
            
            // 2. 如果参数中没有，尝试从HTTP会话中获取（适用于已登录用户）
            if (userId == null || userId.trim().isEmpty()) {
                HttpSession session = httpRequest.getSession(false); // 不创建新会话
                if (session != null) {
                    userId = (String) session.getAttribute("SESSION_USER_ID");
                }
            }
            
            // 3. 如果以上都没有，尝试从请求头中获取令牌并解析（适用于JWT等认证方式）
            if (userId == null || userId.trim().isEmpty()) {
                String token = httpRequest.getHeader("Authorization");
                if (token != null && token.startsWith("Bearer ")) {
                    // 实际项目中应调用JWT工具类解析token获取userId
                    userId = parseUserIdFromToken(token.substring(7)); 
                }
            }
            
            // 4. 验证用户ID（根据业务需求决定是否允许匿名访问）
            if (userId == null || userId.trim().isEmpty()) {
                // 拒绝匿名用户（如果业务允许匿名，可设置userId为随机值）
                System.out.println("握手失败：未提供有效的用户标识");
                return false;
            }
            
            // 5. 将用户ID存入会话属性，后续可在WebSocketHandler中通过session.getAttributes()获取
            attributes.put("userId", userId);
            System.out.println("握手成功，用户ID：" + userId);
            return true;
        }
        
        // 非Servlet环境下拒绝握手（通常不会发生）
        return false;
    }

    /**
     * 握手后执行：可用于记录日志或后续处理
     */
    @Override
    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response,
                               WebSocketHandler wsHandler, Exception exception) {
        if (exception != null) {
            System.err.println("握手完成但发生异常：" + exception.getMessage());
        } else {
            System.out.println("握手完成，连接即将升级为WebSocket");
        }
    }

    /**
     * 从令牌中解析用户ID（示例方法，实际需根据项目的认证方式实现）
     */
    private String parseUserIdFromToken(String token) {
        // 实际实现中应：
        // 1. 验证token签名
        // 2. 解析token payload获取用户ID
        // 3. 检查token有效期
        // 此处为示例，直接返回模拟的用户ID
        return "user_from_token_" + token.substring(0, 6);
    }
}
